home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
misc
/
umentiler.lha
/
Umentiler
/
source
/
Umentiler.c
< prev
Wrap
C/C++ Source or Header
|
1995-10-28
|
21KB
|
927 lines
/*************************************************************************
*
* Umentiler
*
* Copyright ⌐1995 Lee Kindness cs2lk@scms.rgu.ac.uk
*
* Read Umentiler.guide (from the main archive) for distribution details.
*
* Umentiler.c
*/
/* Includes are kept in gst.c for gst compilation purposes */
#include "gst.c"
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
extern struct LocaleBase *LocaleBase;
/* Revision information */
#include "Umentiler_rev.h"
/* Version String */
const char ver[] = VERSTAG;
/*
* Keep all 'global' vars in a locally allocated and
* passed around structure => Gives pure, reentrant code.
*/
struct Vars
{
ULONG v_Tags_p;
ULONG v_Tags_e;
ULONG v_Tags_i;
struct Locale *v_Locale;
struct LocaleBase *v_LocaleBase;
};
/* Prototypes */
STRPTR strsistr (STRPTR, STRPTR);
VOID AddC2Cmd (STRPTR, char);
VOID MFPutC (BPTR, char, BOOL);
VOID RepMarkers (struct Vars *, STRPTR, BPTR, BOOL);
VOID HInsertion (struct Vars *, BPTR, STRPTR, ULONG);
VOID HInsertCmd (struct Vars *, BPTR, STRPTR);
ULONG __asm LFFunc (register __a0 struct Hook *,
register __a2 struct Locale *,
register __a1 char);
VOID HDateCmd (struct Vars *, BPTR, STRPTR, STRPTR,
LONG, BOOL, BOOL, BOOL);
VOID HVersionCmd (BPTR, STRPTR, BOOL, BOOL, BOOL, BOOL);
VOID HProgramCmd (struct Vars *, BPTR, STRPTR, BOOL);
VOID HVarCmd (BPTR, STRPTR, BOOL, BOOL, BOOL);
VOID HSetvarCmd (STRPTR, STRPTR);
/* Template for all temp file names */
#define TMP_TEMP "T:UXXXXXX.XXX"
/*************************************************************************
* strsistr() - returns s if f occurs at the start of s. Case insensitive.
*/
STRPTR strsistr(STRPTR s, STRPTR f)
{
if( s && f )
{
BOOL match = TRUE;
for( ; *s && *f && match; ++s, ++f )
if( toupper(*s) != toupper(*f) )
match = FALSE;
if( match )
return( s );
else
return( NULL );
} else
return( NULL );
}
/*************************************************************************
* AddC2Cmd() - Add a charcter to the command string
*/
VOID AddC2Cmd(STRPTR cmd, char ch)
{
STRPTR s;
/* Find the null */
s = strchr(cmd, '\0');
/* Add the char */
*s = ch;
/*
* ++s;
* *s = '\0'
*
* (no need, we MEMF_CLEARed it)
*/
}
/*************************************************************************
* MFPutC() - Will FPutC if certain conditions.
*/
VOID MFPutC(BPTR file, char ch, BOOL nolines)
{
if( !(nolines && ch == '\n') )
FPutC(file, ch);
}
/*************************************************************************
* HInsertion() - Insert text into the file
*/
/* Commands */
#define TXT_INSERT "INSERT"
#define CMD_INSERT 1
#define TXT_DATE "DATE"
#define CMD_DATE 2
#define TXT_VERSION "VERSION"
#define CMD_VERSION 3
#define TXT_PROGRAM "PROGRAM"
#define CMD_PROGRAM 4
#define TXT_VAR "VAR"
#define CMD_VAR 5
#define TXT_SETVAR "SETVAR"
#define CMD_SETVAR 6
/* And ReadArg() templates for each */
#define TMP_INSERT "FILE/A"
#define OPT_INSERT_FILE 0
#define TMP_DATE "FROM/K,LF=LOCALEFORMAT/K,F=FORMAT/N/K,NY=NODAY/S,ND=NODATE/S,NT=NOTIME/S"
#define OPT_DATE_FROM 0
#define OPT_DATE_LOCALEFORMAT 1
#define OPT_DATE_FORMAT 2
#define OPT_DATE_NODAY 3
#define OPT_DATE_NODATE 4
#define OPT_DATE_NOTIME 5
#define TMP_VERSION "FROM/A,F=FULL/S,NN=NONAME/S,NV=NOVER/S,ND=NODATE/S"
#define OPT_VERSION_FROM 0
#define OPT_VERSION_FULL 1
#define OPT_VERSION_NONAME 2
#define OPT_VERSION_NOVER 3
#define OPT_VERSION_NODATE 4
#define TMP_PROGRAM "NL=NOLINES/S,CMDLINE/A/F"
#define OPT_PROGRAM_NOLINES 0
#define OPT_PROGRAM_CMDLINE 1
#define TMP_VAR "FROM/A,NL=NEWLINE/S,G=GLOBAL/S,L=LOCAL/S"
#define OPT_VAR_FROM 0
#define OPT_VAR_NEWLINE 1
#define OPT_VAR_GLOBAL 2
#define OPT_VAR_LOCAL 3
#define TMP_SETVAR "NAME/A,TEXT/A/F"
#define OPT_SETVAR_NAME 0
#define OPT_SETVAR_TEXT 1
/* Maximum number of options */
#define OPT_ALL_MAX (OPT_DATE_NOTIME + 1)
#define NOARG "\n"
VOID HInsertion(struct Vars *vars, BPTR destf, STRPTR cmd, ULONG cmdsize)
{
STRPTR s, arg, temp;
LONG cnum;
/* Skip any initial white space */
cmd = stpblk(cmd);
/* skip to the arguments */
if( arg = strpbrk(cmd, "\t ") )
arg = stpblk(arg);
else
arg = NOARG;
/* What command ? */
if( s = strsistr(cmd, TXT_INSERT) )
{
cnum = CMD_INSERT;
temp = TMP_INSERT;
} else if( s = strsistr(cmd, TXT_DATE) )
{
cnum = CMD_DATE;
temp = TMP_DATE;
} else if( s = strsistr(cmd, TXT_VERSION) )
{
cnum = CMD_VERSION;
temp = TMP_VERSION;
} else if( s = strsistr(cmd, TXT_PROGRAM) )
{
cnum = CMD_PROGRAM;
temp = TMP_PROGRAM;
} else if( s = strsistr(cmd, TXT_VAR) )
{
cnum = CMD_VAR;
temp = TMP_VAR;
} else if( s = strsistr(cmd, TXT_SETVAR) )
{
cnum = CMD_SETVAR;
temp = TMP_SETVAR;
} else
{
PrintFault(ERROR_ACTION_NOT_KNOWN, cmd);
cnum = 0;
temp = NULL;
++vars->v_Tags_i;
}
if( cnum && temp && arg )
{
struct RDArgs *rda;
/* Add a newline to the end of cmd (for ReadArgs()) */
if( *cmd != '\n' )
AddC2Cmd(cmd, '\n');
if( rda = AllocDosObject(DOS_RDARGS, NULL) )
{
STRPTR args[OPT_ALL_MAX];
rda->RDA_DAList = NULL;
rda->RDA_Flags |= RDAF_NOPROMPT;
rda->RDA_Buffer = NULL;
rda->RDA_Source.CS_Buffer = arg;
rda->RDA_Source.CS_Length = strlen(arg);
rda->RDA_Source.CS_CurChr = 0;
memset(&args, 0, (sizeof(STRPTR) * OPT_ALL_MAX));
/* Parse argumesnts for the option */
if( ReadArgs(temp, (LONG *)&args, rda) )
{
switch( cnum )
{
case CMD_INSERT :
HInsertCmd(vars, destf, args[OPT_INSERT_FILE]);
break;
case CMD_VERSION :
HVersionCmd(destf, args[OPT_VERSION_FROM],
(BOOL)args[OPT_VERSION_FULL],
(BOOL)args[OPT_VERSION_NONAME],
(BOOL)args[OPT_VERSION_NOVER],
(BOOL)args[OPT_VERSION_NODATE]);
break;
case CMD_PROGRAM :
HProgramCmd(vars, destf, args[OPT_PROGRAM_CMDLINE],
(BOOL)args[OPT_PROGRAM_NOLINES]);
break;
case CMD_DATE :
HDateCmd(vars, destf, args[OPT_DATE_FROM],
args[OPT_DATE_LOCALEFORMAT],
args[OPT_DATE_FORMAT] ? *((LONG *)args[OPT_DATE_FORMAT]) : 0,
(BOOL)args[OPT_DATE_NODAY],
(BOOL)args[OPT_DATE_NODATE],
(BOOL)args[OPT_DATE_NOTIME]);
break;
case CMD_VAR :
HVarCmd(destf, args[OPT_VAR_FROM],
(BOOL)args[OPT_VAR_NEWLINE],
(BOOL)args[OPT_VAR_GLOBAL],
(BOOL)args[OPT_VAR_LOCAL]);
break;
case CMD_SETVAR :
HSetvarCmd(args[OPT_SETVAR_NAME],
args[OPT_SETVAR_TEXT]);
break;
}
++vars->v_Tags_p;
FreeArgs(rda);
} else
++vars->v_Tags_i;
FreeDosObject(DOS_RDARGS, rda);
}
}
/* Clear cmd */
memset(cmd, 0, cmdsize);
}
/*************************************************************************
* HInsertCmd() - Handle the INSERT command.
*/
VOID HInsertCmd(struct Vars *vars, BPTR destf, STRPTR from)
{
/* paste a file
* We simply recurse, call RepMarkers()
*/
RepMarkers(vars, from, destf, FALSE);
}
/*************************************************************************
* HVersionCmd() - Handle the VERSION command.
*/
#define VERSION_CMD_1ST_PART "Version "
#define VERSION_CMD_2ND_PART " FULL"
#define VERBUF_SIZE 256
#define STATE_NAME 0
#define STATE_VERSION 1
#define STATE_DATE 2
VOID HVersionCmd(BPTR destf, STRPTR from, BOOL full, BOOL noname, BOOL nover, BOOL nodate)
{
STRPTR cmd;
/* Alloc cmd */
if( cmd = AllocVec(strlen(VERSION_CMD_1ST_PART) +
strlen(VERSION_CMD_2ND_PART) +
strlen(from) + 1, 0) )
{
STRPTR tmpname;
/* build the command line */
strcpy(cmd, VERSION_CMD_1ST_PART);
strcat(cmd, from);
strcat(cmd, VERSION_CMD_2ND_PART);
/* Alloc tmpname */
if( tmpname = AllocVec(14, 0) )
{
strcpy(tmpname, TMP_TEMP);
mktemp(tmpname);
if( *tmpname != 0 )
{
BPTR tf;
/* Open temp file */
if( tf = Open(tmpname, MODE_NEWFILE) )
{
BPTR inf;
/* Open input file */
if( inf = Open("NIL:", MODE_OLDFILE) )
{
if( SystemTags(cmd, SYS_Input, inf,
SYS_Output, tf,
TAG_DONE) == 0 )
{
STRPTR verbuf;
/* Version command successful, alloc verbuf */
if( verbuf = AllocVec(VERBUF_SIZE, 0) )
{
/* Seek to start */
Seek(tf, 0, OFFSET_BEGINNING);
/* Read first line */
if( FGets(tf, verbuf, VERBUF_SIZE-1) )
{
STRPTR s;
LONG state = STATE_NAME;
/* Remove trailing EOL */
if( s = strchr(verbuf, '\n') )
*s = '\0';
if( !full )
{
for( s = verbuf; *s ; ++s )
{
switch( state )
{
case STATE_NAME :
if( isspace(*s) )
{
state++;
if( (!noname && !nover) ||
(!noname && nover && !nodate) )
FPutC(destf, ' ');
s = stpblk(s);
--s;
} else
{
if( !noname )
FPutC(destf, *s);
}
break;
case STATE_VERSION :
if( isspace(*s) )
{
state++;
if( !nover && !nodate )
FPutC(destf, ' ');
s = stpblk(s);
--s;
} else
{
if( !nover )
FPutC(destf, *s);
}
break;
case STATE_DATE :
if( (*s != '(') && (*s != ')') && !nodate )
FPutC(destf, *s);
break;
}
}
} else
FPuts(destf, verbuf);
}
FreeVec(verbuf);
}
} else
PrintFault(IoErr(), from);
Close(inf);
}
Close(tf);
DeleteFile(tmpname);
}
}
FreeVec(tmpname);
}
FreeVec(cmd);
}
}
/*************************************************************************
* HProgramCmd() - Handle the PROGRAM command.
*/
VOID HProgramCmd(struct Vars *vars, BPTR destf, STRPTR cmdline, BOOL noline)
{
STRPTR tmpname;
/* Alloc tmpname */
if( tmpname = AllocVec(14, 0) )
{
strcpy(tmpname, TMP_TEMP);
mktemp(tmpname);
if( *tmpname != 0 )
{
BPTR tf;
/* Open temp file */
if( tf = Open(tmpname, MODE_NEWFILE) )
{
if( SystemTags(cmdline, SYS_Output, tf, TAG_END) == 0 )
{
Close(tf);
tf = 0;
/* Recurse */
RepMarkers(vars, tmpname, destf, noline);
} else
PrintFault(IoErr(), cmdline);
if( tf )
Close(tf);
DeleteFile(tmpname);
}
}
FreeVec(tmpname);
}
}
/*************************************************************************
* LFFunc() - Hook function for use in HDateCmd() by FormatDate().
*/
/*
* NOTE: no __saveds keyword, we dont need it and it would make us unpure
*/
ULONG __asm LFFunc(register __a0 struct Hook *hook,
register __a2 struct Locale *locale,
register __a1 char ch)
{
/* hook->h_Data contains a BPTR of the file to output to */
if( ch )
FPutC((BPTR)hook->h_Data, ch);
return( TRUE );
}
/*************************************************************************
* HDateCmd() - Handle the DATE command.
*/
VOID HDateCmd(struct Vars *vars, BPTR destf, STRPTR from, STRPTR localeformat, LONG format,
BOOL noday, BOOL nodate, BOOL notime)
{
struct DateStamp *ds = NULL;
/* Get the datestamp */
if( from )
{
BPTR l;
/* Read it from a file */
if( l = Lock(from, ACCESS_READ) )
{
struct FileInfoBlock *fib;
/* Alloc fib */
if( fib = AllocDosObject(DOS_FIB, NULL) )
{
if( Examine(l, fib) )
{
if( ds = AllocVec(sizeof(struct DateStamp), 0) )
{
/* Copy ds from the fib */
memcpy(ds, &fib->fib_Date, sizeof(struct DateStamp));
}
}
FreeDosObject(DOS_FIB, fib);
}
UnLock(l);
} else
PrintFault(IoErr(), from);
} else
{
if( ds = AllocVec(sizeof(struct DateStamp), 0) )
ds = DateStamp(ds);
}
if( ds )
{
/* Are we going to be locale or dos function based? */
if( localeformat && vars->v_Locale )
{
struct Hook *LFHook;
if( LFHook = AllocVec(sizeof(struct Hook), MEMF_CLEAR) )
{
LFHook->h_Entry = (HOOKFUNC)LFFunc;
/* Pass the file handle */
LFHook->h_Data = (APTR)destf;
FormatDate(vars->v_Locale, localeformat, ds, LFHook);
FreeVec(LFHook);
}
} else
{
unsigned char daystr[LEN_DATSTRING], datestr[LEN_DATSTRING], timestr[LEN_DATSTRING];
struct DateTime *dt;
if( dt = AllocVec(sizeof(struct DateTime), MEMF_CLEAR) )
{
memcpy(&dt->dat_Stamp, ds, sizeof(struct DateStamp));
dt->dat_Format = format;
dt->dat_StrDay = (STRPTR)&daystr;
dt->dat_StrDate = (STRPTR)&datestr;
dt->dat_StrTime = (STRPTR)×tr;
if( DateToStr(dt) )
{
if( !noday )
{
FPuts(destf, dt->dat_StrDay);
if( !nodate || (nodate && !notime) )
FPutC(destf, ' ');
}
if( !nodate )
{
FPuts(destf, dt->dat_StrDate);
if( !notime )
FPutC(destf, ' ');
}
if( !notime )
FPuts(destf, dt->dat_StrTime);
}
FreeVec(dt);
}
}
FreeVec(ds);
}
}
/*************************************************************************
* HVarCmd() - Handle the VAR command.
*/
#define VAR_BUFFER_SIZE 512
VOID HVarCmd(BPTR destf, STRPTR from, BOOL newline, BOOL global, BOOL local)
{
STRPTR buffer;
/* Alloc buffer */
if( buffer = AllocVec(VAR_BUFFER_SIZE, 0) )
{
ULONG flags = LV_VAR;
if( global )
flags |= GVF_GLOBAL_ONLY;
else if( local )
flags |= GVF_LOCAL_ONLY;
if( GetVar(from, buffer, VAR_BUFFER_SIZE, flags) != -1 )
{
FPuts(destf, buffer);
if( newline )
FPutC(destf, '\n');
} else
PrintFault(IoErr(), from);
FreeVec(buffer);
}
}
/*************************************************************************
* HSetvarCmd() - Handle the SETVAR command.
*/
VOID HSetvarCmd(STRPTR name, STRPTR text)
{
SetVar(name, text, -1, LV_VAR | GVF_LOCAL_ONLY);
}
/*************************************************************************
* RepMarkers() - Parse a file and replace 'stuff'
*/
/* Command introducors and terminators */
#define INTRODUCER_1 '/'
#define INTRODUCER_2 '>' /* INTRODUCER = "/>" */
#define TERMINATOR_1 '<'
#define TERMINATOR_2 '\\' /* TERMINATOR = "<\" */
#define ESCAPE_CHAR '!'
/* When read thru a line char by char we can by in any of these states */
#define LEV_ESCAPED_2 -2
#define LEV_ESCAPED_1 -1
#define LEV_NONE 0
#define LEV_1 1
#define LEV_2 2
#define LEV_3 3
#define BUFFER_SIZE 256
#define CMD_BUF_SIZE strlen(buffer)+2
VOID RepMarkers(struct Vars *vars, STRPTR source, BPTR destf, BOOL nolines)
{
BPTR sourcef;
/* Open source file */
if( sourcef = Open(source, MODE_OLDFILE) )
{
APTR buf;
/* Alloc buf */
if( buf = AllocVec(BUFFER_SIZE, 0) )
{
APTR buffer;
/* Go thru the source file, line by line */
while( buffer = FGets(sourcef, buf, BUFFER_SIZE-1) )
{
STRPTR cmd;
/* Alloc cmd buffer.
* strlen(buffer)+2, 1 extra for the null and 1 more cause we add
* on a '\n' in HInsertion()
*/
if( cmd = AllocVec(CMD_BUF_SIZE, MEMF_CLEAR) )
{
register STRPTR s;
register LONG level = LEV_NONE;
/*
* For each line we parse each character in a
* state machine manner.
*/
for( s = buffer; *s ; ++s )
{
switch( level )
{
case LEV_ESCAPED_1 :
switch( *s )
{
case INTRODUCER_1 :
level = LEV_ESCAPED_2;
break;
case ESCAPE_CHAR :
level = LEV_ESCAPED_1;
FPutC(destf, (LONG)ESCAPE_CHAR);
break;
default:
level = LEV_NONE;
FPutC(destf, (LONG)ESCAPE_CHAR);
MFPutC(destf, (LONG)*s, nolines);
break;
}
break;
case LEV_ESCAPED_2 :
if( *s == INTRODUCER_2 )
{
FPutC(destf, (LONG)INTRODUCER_1);
FPutC(destf, (LONG)INTRODUCER_2);
++vars->v_Tags_e;
} else
{
FPutC(destf, (LONG)ESCAPE_CHAR);
FPutC(destf, (LONG)INTRODUCER_1);
MFPutC(destf, (LONG)*s, nolines);
}
level = LEV_NONE;
break;
case LEV_NONE :
switch( *s )
{
case INTRODUCER_1 :
level = LEV_1;
break;
case ESCAPE_CHAR :
level = LEV_ESCAPED_1;
break;
default :
level = LEV_NONE;
MFPutC(destf, (LONG)*s, nolines);
break;
}
break;
case LEV_1 :
if( *s == INTRODUCER_2 )
level = LEV_2;
else
{
level = LEV_NONE;
FPutC(destf, (LONG)INTRODUCER_1);
MFPutC(destf, (LONG)*s, nolines);
}
break;
case LEV_2 :
if( *s == TERMINATOR_1 )
level = LEV_3;
else
AddC2Cmd(cmd, *s);
break;
case LEV_3 :
if( *s == TERMINATOR_2 )
{
level = LEV_NONE;
HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
} else
{
level = LEV_2;
AddC2Cmd(cmd, TERMINATOR_1);
AddC2Cmd(cmd, *s);
}
break;
}
}
/* Do insertion if cmd has something in it (ie non terminated cmd) */
if( *cmd != '\0' )
{
HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
MFPutC(destf, '\n', nolines);
}
FreeVec(cmd);
}
}
FreeVec(buffer);
}
Close(sourcef);
} else
PrintFault(IoErr(), source);
}
/*************************************************************************
* main() - Ehhh... It's kinda ehhh...
*/
int main( VOID )
{
LONG rc = 10;
if( (((struct Library *)DOSBase)->lib_Version > 35) &&
(((struct Library *)SysBase)->lib_Version > 35) )
{
struct Vars *vars;
/* Allocate var structure */
if( vars = AllocVec(sizeof(struct Vars), MEMF_CLEAR) )
{
struct RDArgs *rdargs;
#define TEMPLATE "SOURCE/A,DESTINATION,QUIET/S"
#define OPT_SOURCE 0
#define OPT_DEST 1
#define OPT_QUIET 2
#define OPT_MAX 3
STRPTR args[OPT_MAX] = {0, 0, 0};
#define ARG_SOURCE args[OPT_SOURCE]
STRPTR ARG_DEST;
#define ARG_QUIET (BOOL)args[OPT_QUIET]
/* Open Locale */
if( vars->v_LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library", 38) )
vars->v_Locale = OpenLocale(NULL);
else
vars->v_Locale = NULL;
LocaleBase = vars->v_LocaleBase;
/* Parse arguments */
if (rdargs = ReadArgs(TEMPLATE, (LONG *)&args, NULL))
{
BPTR srcl;
ARG_DEST = args[OPT_DEST];
/* Lock source */
if( srcl = Lock(ARG_SOURCE, ACCESS_READ) )
{
BOOL makefilename = FALSE;
BOOL destok = TRUE;
if( ARG_DEST )
{
BPTR destl;
/* Try to lock dest */
if( destl = Lock(ARG_DEST, ACCESS_READ) )
{
/* Same file? */
if( SameLock(srcl, destl) == LOCK_SAME )
{
destok = FALSE;
SetIoErr(ERROR_OBJECT_EXISTS);
}
UnLock(destl);
}
} else
makefilename = TRUE;
if( makefilename )
{
/* Use a temp file */
if( ARG_DEST = AllocVec(14, 0) )
{
strcpy(ARG_DEST, TMP_TEMP);
mktemp(ARG_DEST);
if( *ARG_DEST != 0 )
destok = TRUE;
}
}
if( destok )
{
BPTR destf;
if( destf = Open(ARG_DEST, MODE_NEWFILE) )
{
RepMarkers(vars, ARG_SOURCE, destf, FALSE);
Close(destf);
if( !ARG_QUIET )
{
if( vars->v_Tags_p )
Printf("%ld tags processed\n", vars->v_Tags_p);
if( vars->v_Tags_e )
Printf("%ld tags escaped\n", vars->v_Tags_e);
if( vars->v_Tags_i )
Printf("%ld invalid tags\n", vars->v_Tags_i);
}
rc = 0;
}
}
UnLock(srcl);
if( makefilename )
{
if( rc == 0)
{
BPTR src;
/* Copy ARG_DEST to ARG_SOURCE */
if( src = Open(ARG_DEST, MODE_OLDFILE) )
{
BPTR dest;
if( dest = Open(ARG_SOURCE, MODE_NEWFILE) )
{
LONG ch;
for( ch = FGetC(src); ch != -1; ch = FGetC(src) )
FPutC(dest, ch);
Close(dest);
}
Close(src);
}
}
/* Delete the temp file */
DeleteFile(ARG_DEST);
/* Free name buffer */
FreeVec(ARG_DEST);
}
}
FreeArgs(rdargs);
}
if( vars->v_Locale )
CloseLocale(vars->v_Locale);
if( vars->v_LocaleBase )
CloseLibrary((struct Library *)vars->v_LocaleBase);
FreeVec(vars);
}
}
if( rc )
PrintFault(IoErr(), "Umentiler");
return( rc );
}